package com.example.patient.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.example.common.entity.ClientBaseInfo;
import com.example.common.entity.OrderMain;
import com.example.common.entity.RxMain;
import com.example.common.support.ApiException;
import com.example.common.utils.CheckUtils;
import com.example.patient.dto.resp.OrderInfoResp;
import com.example.patient.dto.resp.OrderPayResp;
import com.example.patient.jpa.ClientBaseInfoRepository;
import com.example.patient.jpa.OnlineConsultationRepository;
import com.example.patient.jpa.OrderMainRepository;
import com.example.patient.jpa.RxMainRepository;
import com.example.patient.properties.WxProp;
import com.example.patient.service.PayService;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author wxy
 * @Date 2021/1/18 9:55
 * @Version 1.0
 */
@Service
public class PayServiceImpl implements PayService {
    @Resource
    private OrderMainRepository orderMainRepository;
    @Resource
    private OnlineConsultationRepository onlineConsultationRepository;
    @Resource
    private RxMainRepository rxMainRepository;
    @Resource
    private ClientBaseInfoRepository clientBaseInfoRepository;

    @Resource
    private WxProp wxProp;
    @Resource
    private HttpServletRequest request;

    /**
     * 订单详情
     */
    @Override
    public OrderInfoResp orderInfo(String orderNo, Integer oType) {
        CheckUtils.checkNull(orderNo, new ApiException(1, "订单号不能为空"));
        CheckUtils.checkNull(oType, new ApiException(1, "订单类型不能为空"));

        BigDecimal money = null;
        String orderType = null;
        //1:问诊订单；2:处方订单；3:商城订单
        switch (oType) {
            case 1:
                OrderMain orderMain = orderMainRepository.findById(orderNo).orElseThrow(() -> new ApiException(1, "未查询到数据"));
                money = orderMain.getAskMoney();
                orderType = "问诊订单";
                Long count = onlineConsultationRepository.countByDcIdAndPidAndOcStatusIn(orderMain.getDcId(), orderMain.getPid(), Arrays.asList(0, 1));
                Boolean have = 0 == count ? Boolean.FALSE : Boolean.TRUE;
                if (have) {
                    throw new ApiException(1, "已存在有效问诊");
                }
                break;
            case 2:
                RxMain rxMain = rxMainRepository.findById(orderNo).orElseThrow(() -> new ApiException(1, "未查询到数据"));
                money = rxMain.getSalePrice();
                orderType = "处方订单";
                break;
            case 3:
            default:
                break;
        }
        if (null != money) {
            money = money.divide(new BigDecimal("1"), 2, BigDecimal.ROUND_DOWN);
        }
        OrderInfoResp resp = new OrderInfoResp();
        resp.setMoney(null == money ? new BigDecimal("0").toString() : money.toString());
        resp.setOrderNo(orderNo);
        resp.setOrderType(orderType);
        return resp;
    }

    /**
     * 发起支付
     */
    @Override
    public OrderPayResp orderPay(String orderNo, Integer oType, String wapay) {
        CheckUtils.checkNull(orderNo, new ApiException(1, "订单号不能为空"));
        CheckUtils.checkNull(oType, new ApiException(1, "订单类型不能为空"));

        String appId;
        String callBack;
        String mchId = wxProp.getMchId();
        String mchKey = wxProp.getMchKey();
        //H5调起JS API参数 用于小程序   true 小程序支付  false 公众号支付
        boolean isWaPay = !StringUtils.isEmpty(wapay) && wapay.equals("2");
        if (isWaPay) {
            appId = wxProp.getWxAppletsAppId();
            callBack = wxProp.getWxAppletsCallBack();
        } else {
            appId = wxProp.getWxPublicAppId();
            callBack = wxProp.getWxPublicCallBack();
        }

        //订单验证
        String orderType;
        BigDecimal money;
        Long uid;
        switch (oType) {
            case 1:
                OrderMain orderMain = orderMainRepository.findById(orderNo).orElseThrow(() -> new ApiException(1, "未查询到数据"));
                money = orderMain.getAskMoney();
                uid = orderMain.getClientID();
                orderType = "问诊订单";
                Long count = onlineConsultationRepository.countByDcIdAndPidAndOcStatusIn(orderMain.getDcId(), orderMain.getPid(), Arrays.asList(0, 1));
                Boolean have = 0 == count ? Boolean.FALSE : Boolean.TRUE;
                if (have) {
                    throw new ApiException(1, "已存在有效问诊");
                }
                break;
            case 2:
                RxMain rxMain = rxMainRepository.findById(orderNo).orElseThrow(() -> new ApiException(1, "未查询到数据"));
                money = rxMain.getSalePrice();
                OrderMain orderMain1 = orderMainRepository.findById(rxMain.getOrderNO()).orElseThrow(() -> new ApiException(1, "未查询到数据"));
                uid = orderMain1.getClientID();
                orderType = "处方订单";
                break;
            case 3:
            default:
                throw new ApiException(1, "暂不支持此类型");
        }
        money = money.multiply(new BigDecimal("100"));

        ClientBaseInfo clientBaseInfo = clientBaseInfoRepository.findById(uid).orElseThrow(() -> new ApiException(1, "未查询到数据"));
        String openId = clientBaseInfo.getOpenId();

        return appletsPay(appId, mchId, mchKey, orderType, openId, money, callBack, orderNo);
    }

    private OrderPayResp appletsPay(String appId, String mchId, String mchKey, String orderType, String openId, BigDecimal money, String callBack, String orderNo) {
        //微信支付小程序与
        WxPayService wxPayService = new WxPayServiceImpl();
        WxPayConfig wxPayConfig = new WxPayConfig();
        wxPayConfig.setAppId(appId);
        wxPayConfig.setMchId(mchId);
        wxPayConfig.setMchKey(mchKey);
        wxPayService.setConfig(wxPayConfig);
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = WxPayUnifiedOrderRequest.newBuilder().build();
        wxPayUnifiedOrderRequest.setNonceStr(RandomUtil.randomString(10));
        wxPayUnifiedOrderRequest.setBody(orderType);
        wxPayUnifiedOrderRequest.setOutTradeNo(orderNo);
        wxPayUnifiedOrderRequest.setOpenid(openId);
        wxPayUnifiedOrderRequest.setTotalFee(money.intValue());
        wxPayUnifiedOrderRequest.setSpbillCreateIp(request.getRemoteAddr());
        wxPayUnifiedOrderRequest.setNotifyUrl(callBack);
        wxPayUnifiedOrderRequest.setTradeType("JSAPI");

        OrderPayResp orderPayResp = new OrderPayResp();
        WxPayUnifiedOrderResult wxPayUnifiedOrderResult;
        try {
            wxPayUnifiedOrderResult = wxPayService.unifiedOrder(wxPayUnifiedOrderRequest);
            Map<String, String> map = new HashMap<>();
            map.put("appId", appId);
            map.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
            map.put("nonceStr", wxPayUnifiedOrderResult.getNonceStr());
            map.put("package", "prepay_id=" + wxPayUnifiedOrderResult.getPrepayId());
            map.put("signType", "MD5");
            String sign2 = WXPayUtil.generateSignature(map, mchKey, WXPayConstants.SignType.MD5);

            orderPayResp.setTimeStamp(String.valueOf(System.currentTimeMillis() / 1000));
            orderPayResp.setNonceStr(wxPayUnifiedOrderResult.getNonceStr());
            orderPayResp.setPackage("prepay_id=" + wxPayUnifiedOrderResult.getPrepayId());
            orderPayResp.setSignType("MD5");
            orderPayResp.setPaySign(sign2);
        } catch (Exception e) {
            throw new ApiException(1, e.getMessage());
        }
        return orderPayResp;
    }

}
